package com.alinesno.cloud.gateway.core.dispather.socket.coder;

import java.util.List;

import com.alinesno.cloud.gateway.core.dispather.socket.bean.ResponseMessageBean;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import io.netty.util.CharsetUtil;

/**
 * 类负责创建的 MemcachedResponse 读取字节
	代表当前解析状态,这意味着我们需要解析的头或 body
	根据解析状态切换
	如果不是至少24个字节是可读的,它不可能读整个头部,所以返回这里,等待再通知一次数据准备阅读
	阅读所有头的字段
	检查是否足够的数据是可读用来读取完整的响应的 body。长度是从头读取
	检查如果有任何额外的 flag 用于读，如果是这样做
	检查如果响应包含一个 expire 字段，有就读它
	检查响应是否包含一个 key ,有就读它
	读实际的 body 的 payload
	从前面读取字段和数据构造一个新的 MemachedResponse
 * @author LuoAnDong
 * @since 2019年9月21日 下午8:58:33
 */
public class ResponseMessageDecoder extends ByteToMessageDecoder {  
	
    private enum State { 
        Header,
        Body
    }

    private State state = State.Header;
    private int totalBodySize;
    private byte magic;
    private int length ; 

    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) { 
    	
        switch (state) { 
            case Header:
                if (in.readableBytes() < 12) {
                    return;
                }
                magic = in.readByte();  //4位
                length = Integer.parseInt(in.readSlice(8).toString(CharsetUtil.UTF_8)) ; //8位长度
                
                totalBodySize = in.readInt();

                state = State.Body;
            case Body:
                if (in.readableBytes() < totalBodySize) {
                    return; 
                }
                int actualBodySize = totalBodySize;
                
                ByteBuf body = in.readBytes(actualBodySize);  //10
                String data = body.toString(CharsetUtil.UTF_8);
                
                ResponseMessageBean message = new ResponseMessageBean() ; 
                message.setMagic(magic); 
                message.setLength(length); 
                message.setData(data); 
                
                state = State.Header;
        }

    }
}